using System;
using Microsoft.Practices.Unity;

namespace Sessionizer.Core.Unity
{
    public static class Extensions
    {
        /// <summary>
        ///     Creates new session.
        /// </summary>
        /// <param name="container">Container for session.</param>
        /// <returns>New session</returns>
        public static ISession Session(this IUnityContainer container)
        {
            return container.Resolve<ISessionFactory>().Create();
        }

        /// <summary>
        ///     Initializes session's data value.
        /// </summary>
        /// <typeparam name="T">Type of session data.</typeparam>
        /// <param name="container">Session container.</param>
        /// <param name="instance">Instance of session data.</param>
        /// <returns>Constructed sessions data container/</returns>
        public static ISessions<T> SetSessions<T>(this IUnityContainer container, T instance)
        {
            var sessions =
                container.Resolve<ISessions<T>>(
                    new DependencyOverride<ISessionsFactory<T>>(new ConcreteSessionsFactory<T>(instance)));
            if (!ReflectionHelper<T>.IsValueType)
            {
                if (ReferenceEquals(sessions.Instance, instance))
                {
                    return sessions;
                }
            }
            else
            {
                if (instance.Equals(sessions.Instance))
                {
                    return sessions;
                }
            }
            throw new InvalidOperationException("Session value has already been set");
        }

        /// <summary>
        ///     Gets session data instance.
        /// </summary>
        /// <typeparam name="T">Type of session data.</typeparam>
        /// <param name="container">Container for session.</param>
        /// <returns>Session data instance of given type.</returns>
        public static T GetSessions<T>(this IUnityContainer container)
        {
            return container.Resolve<ISessions<T>>().Instance;
        }
    }
}